`timescale 1ns/1ns 
// 请设计状态机电路，实现自动售卖机功能，A饮料5元钱，B饮料10元钱，售卖机可接收投币5元钱和10元钱，每次投币只可买一种饮料，
// 考虑找零的情况。
// 电路的接口如下图所示。sel信号会先于din信号有效，且在购买一种饮吹料时值不变
// sel为选择信号，用来选择购买饮料的种类，sel=0,表示购买A饮料，sel=1,表示购买B饮料；
// din表示投币输入，din=0表示未投币，din=1表示投币5元，din=2表示投币10元，不会出现din=3的情沉；
// drinks ou表示料输出，drinks out=-0表示没有饮输出，drinks out=1表示输出A料，drinks out=2表示输出B饮料，
// 不出现drinks out=3的
// 青况，输出有效仅保持一个时钟周期；
// change._out表示找零输出，change_out=O表示没有找零，change._out=1表示找零5元，输出有效仅保持个时钟周期。

module sale(
           input clk,
           input rst_n,
           input sel,
           input [1: 0] din,

           output reg [1: 0] drinks_out,
           output reg change_out
       );

parameter id = 3'd0;
parameter s5 = 3'd1;
parameter s10 = 3'd2;
parameter s15 = 3'd3;


reg [2: 0] state;
reg [2: 0] state_next;

always@(posedge clk or negedge rst_n)
	begin
		if (!rst_n)
			state <= 3'd0;
		else
			state <= state_next;
	end

always@( * )
	begin
		if (!rst_n)
			state_next <= id;
		else
			begin
				if (sel == 1'b0)
					begin
						case (state)
							id:
								begin
									if (din == 2'd1)
										state_next <= s5;
									else if (din == 2'd2)
										state_next <= s10;
									else
										state_next <= state_next;
								end
							default:
								state_next <= id;
						endcase

					end
				else if (sel == 1'b1)
					begin
						case (state)
							id:
								begin
									if (din == 2'd1)
										state_next <= s5;
									else if (din == 2'd2)
										state_next <= s10;
									else
										state_next <= state_next;
								end
							s5:
								begin
									if (din == 2'd1)
										state_next <= s10;
									else if (din == 2'd2)
										state_next <= s15;
									else
										state_next <= state_next;
								end
							default:
								state_next <= id;
						endcase
					end
			end
	end

always@(posedge clk or negedge rst_n)
	begin
		if (!rst_n)
			begin
				drinks_out <= 2'd0;
				change_out <= 1'd0;
			end
		else if (sel == 1'b0)
			begin
				case (state_next)
					s5:
						begin
							drinks_out <= 2'd1;
							change_out <= 1'b0;
						end
					s10:
						begin
							drinks_out <= 2'd1;
							change_out <= 1'b1;
						end
				endcase

			end
		else
			begin
				case (state_next)
					s10:
						begin
							drinks_out <= 2'd2;
							change_out <= 1'b0;
						end
					s15:
						begin
							drinks_out <= 2'd2;
							change_out <= 1'b1;
						end
				endcase
			end

	end

endmodule
